#!/usr/bin/perl -wc

package RFCMail::ESMTP::Object::Parameters;

use strict;
use Exporter qw(import);
use Carp qw(croak);
use RFCMail::ESMTP::Grammar::Base qw(PARAMETERS_RE
				     ESMTP_KEYWORD_RE
				     ESMTP_VALUE_RE);
use RFCMail::ESMTP::Grammar::Parser qw(split_parameters_nsc
				       split_esmtp_param_nsc);
use RFCMail::ESMTP::Grammar::Generator qw(encode_esmtp_param_nsc);

our @EXPORT_OK = qw(Parameters);


# Internal format is nested array, as follows:
#   [ [ keyword, value ], ... ]


# note: function, not method
sub Parameters {
    my $self = RFCMail::ESMTP::Object::Parameters->new;
    if (scalar(@_) == 1) {
	$self->add_parameters(@_);
    }
    else {
	$self->add_list(@_);
    }
    return ($self);
}


sub new {
    my $class = shift;
    return (bless [], $class);
}


sub add_parameters {
    my ($self, $parameters) = @_;
    if (defined($parameters)) {
	croak("syntactically invalid parameters string")
	    if not $parameters =~ /\A@{[PARAMETERS_RE]}\z/o;
	push @$self, map { [ split_esmtp_param_nsc($_) ] } split_parameters_nsc($parameters);
    }
    return ($self);
}


sub add_list {
    my $self = shift;
    while (@_) {
	my $keyword = shift;
	croak("syntactically invalid keyword '$keyword'")
	    if not $keyword =~ /\A@{[ESMTP_KEYWORD_RE]}\z/o;
	my $value = shift;
	croak("syntactically invalid value '$value'")
	    if defined($value) and not $value =~ /\A@{[ESMTP_VALUE_RE]}\z/o;
	push @$self, [$keyword, $value];
    }
    return ($self);
}


sub splice_by_pattern {
    my ($self, $pattern) = @_;
    my $result = new(ref($self));
    my $i = scalar(@$self);
    while (--$i >= 0) {
	unshift @$result, splice(@$self, $i, 1)
	    if $self->[$i]->[0] =~ /\A$pattern\z/;
    }
    return ($result);
}


sub subset_by_pattern {
    my ($self, $pattern) = @_;
    my $result = new(ref($self));
    for (@$self) {
	push @$result, $_
	    if $_->[0] =~ /\A$pattern\z/;
    }
    return ($result);
}


sub parameters {
    my ($self) = @_;
    return (undef)
	if not (@$self);
    return (join(" ", map { encode_esmtp_param_nsc(@$_) } @$self));
}


sub list {
    my ($self) = @_;
    return (map { @$_ } @$self);
}


sub list_values {
    my ($self) = @_;
    return (map { $_->[1] } @$self);
}


sub count {
    my ($self) = @_;
    return (scalar(@$self));
}


1;
